home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / MYUTIL / IBM_XBRA.M < prev    next >
Encoding:
Text File  |  1989-04-29  |  6.4 KB  |  270 lines

  1.  
  2. (* TO DO
  3. - Fälle in 'test' überdenken: Ist es sinnvoll, dafür Funktionen bereitzustellen?
  4.   Ansonsten: Dokumentieren, wie Vorgänger (über Carrier.prev) aufgerufen wird.
  5. - Query-Funktion
  6. *)
  7.  
  8. MODULE XBRA;
  9.  
  10. FROM SYSTEM IMPORT ADR, ADDRESS, FLAT, PTR, BYTE, SEG, OFS;
  11.  
  12. FROM InOut IMPORT Write, WriteString, WriteLn, WriteCard, WriteHex, Read;
  13.  
  14.  
  15.  
  16. MODULE X;
  17.  
  18. IMPORT ADR, ADDRESS, FLAT, PTR, BYTE;
  19.  
  20. EXPORT Str4, Carrier, QueryProc,
  21.        Install, Installed, Create, Remove, Query;
  22.  
  23. CONST Magic = 'XBRA';
  24.  
  25. TYPE
  26.       Str4 = ARRAY [0..3] OF CHAR;
  27.  
  28.       JmpCarrier = RECORD
  29.                      instruction: BYTE;
  30.                      operand: ADDRESS
  31.                    END;
  32.  
  33.       Carrier = RECORD
  34.                   magic: Str4;                 (* CONST 'XBRA' *)
  35.                   name : Str4;                 (* individuelle ID *)
  36.                   prev : ADDRESS;              (* voriger Vektor *)
  37.                   entry: JmpCarrier;
  38.                 END;
  39.  
  40.       QueryProc = PROCEDURE ( (* name:   *) Str4,
  41.                               (* call:   *) ADDRESS,
  42.                               (* prev:   *) ADDRESS  ): BOOLEAN;
  43.  
  44. VAR   entryOffs: CARDINAL;
  45.  
  46. VAR   magic: Str4;
  47.  
  48. PROCEDURE equal (VAR s1, s2: Str4): BOOLEAN;
  49.   BEGIN
  50.     RETURN (s1[0]=s2[0]) AND (s1[1]=s2[1]) AND
  51.            (s1[2]=s2[2]) AND (s1[3]=s2[3]);
  52.   END equal;
  53.  
  54. PROCEDURE sub (p: ADDRESS; n: CARDINAL): ADDRESS;
  55.   BEGIN
  56.     RETURN PTR (FLAT (p) - LONG (n))
  57.   END sub;
  58.  
  59. PROCEDURE Installed (name: Str4; vector: ADDRESS; VAR at: ADDRESS): BOOLEAN;
  60.   (*
  61.    * Wird 'name' in Kette ab 'vector' gefunden, enthält 'at' die Adresse
  62.    * des Vektors auf den Funktionseinsprung (welcher Teil von 'Carrier' ist).
  63.    * Wird 'name' nicht gefunden, ist 'at'=vector
  64.    *)
  65.   VAR c: POINTER TO Carrier; p: POINTER TO ADDRESS;
  66.   BEGIN
  67.     at:= vector; (* Vorwahl für RETURN FALSE *)
  68.     p:= vector;
  69.     LOOP
  70.       IF p^ = NIL THEN RETURN FALSE END;
  71.       c:= sub (p^, entryOffs);
  72.       (* hier Exceptions abfangen (aber prüfen, ob vector=exc-vektor ist) *)
  73.       IF equal (c^.magic, magic) THEN
  74.         (* XBRA-Kennung gefunden *)
  75.         IF equal (c^.name, name) THEN
  76.           (* Ende, da Name gefunden *)
  77.           at:= p;
  78.           RETURN TRUE
  79.         ELSE
  80.           (* Vorgänger prüfen *)
  81.           p:= ADR (c^.prev)
  82.         END
  83.       ELSE
  84.         (* Ende, da XBRA-Kette zuende *)
  85.         RETURN FALSE
  86.       END;
  87.     END;
  88.   END Installed;
  89.  
  90. PROCEDURE Create (VAR use: Carrier; name: Str4; call: PROC;
  91.                   VAR entry: ADDRESS);
  92.   (*
  93.    * entry:= <Einsprungadresse der Routine für einen Vektor>
  94.    *)
  95.   BEGIN
  96.     use.name:= name;
  97.     use.magic:= magic;
  98.     use.prev:= NIL;
  99.     use.entry.instruction:= VAL (BYTE, 0EAH);
  100.     use.entry.operand:= ADDRESS (call);
  101.     entry:= ADR (use.entry.instruction)
  102.   END Create;
  103.  
  104. PROCEDURE Install (entry: ADDRESS; at: ADDRESS);
  105.   (*
  106.    * Wenn 'entry'=NIL oder 'at'=NIL, wird ein Laufzeitfehler ausgelöst.
  107.    *)
  108.   VAR c: POINTER TO Carrier; p: POINTER TO ADDRESS;
  109.   BEGIN
  110.     IF (entry = NIL) OR (at = NIL) THEN
  111.       HALT
  112.     ELSE
  113.       c:= sub (entry, entryOffs);
  114.       p:= at;
  115.       c^.prev:= p^;
  116.       p^:= entry;
  117.     END
  118.   END Install;
  119.  
  120. PROCEDURE Remove (at: ADDRESS);
  121.   (*
  122.    * Wenn 'at'=NIL, wird ein Laufzeitfehler ausgelöst.
  123.    *)
  124.   VAR c: POINTER TO Carrier; p: POINTER TO ADDRESS;
  125.   BEGIN
  126.     IF at = NIL THEN
  127.       HALT
  128.     ELSE
  129.       p:= at;
  130.       c:= sub (p^, entryOffs);
  131.       IF equal (c^.magic, magic) THEN
  132.         p^:= c^.prev
  133.       ELSE
  134.         HALT
  135.       END
  136.     END
  137.   END Remove;
  138.  
  139. PROCEDURE Query (vector: ADDRESS; with: QueryProc);
  140.   VAR c: POINTER TO Carrier; p: POINTER TO ADDRESS;
  141.   BEGIN
  142.     p:= vector;
  143.     LOOP
  144.       IF p^ = NIL THEN RETURN END;
  145.       c:= sub (p^, entryOffs);
  146.       IF equal (c^.magic, magic) THEN
  147.         IF NOT with (c^.name, c^.entry.operand, c^.prev) THEN RETURN END;
  148.         p:= ADR (c^.prev)
  149.       ELSE
  150.         IF with ('????', p^, NIL) THEN (* dummy *) END;
  151.         RETURN
  152.       END
  153.     END;
  154.   END Query;
  155.  
  156. PROCEDURE Call (entry: ADDRESS);
  157.   (*
  158.    * Für einfachen Unterprogrammaufruf des Vorgängers von der installierten
  159.    * Routine aus.
  160.    *)
  161.   BEGIN
  162.     HALT
  163.   END Call;
  164.  
  165. VAR testCarr: Carrier;
  166. BEGIN
  167.   magic:= Magic;
  168.   entryOffs:= SHORT (  FLAT (ADR (testCarr.entry.instruction))
  169.                      - FLAT (ADR (testCarr)) )
  170. END X; (* local module *)
  171.  
  172. PROCEDURE norm (a: ADDRESS): ADDRESS;
  173.   BEGIN
  174.     RETURN PTR (FLAT (a))
  175.   END norm;
  176.  
  177. PROCEDURE info (s: ARRAY OF CHAR);
  178.   BEGIN
  179.     WriteString (s);
  180.     WriteLn;
  181.   END info;
  182.  
  183. PROCEDURE WriteAddr (a: ADDRESS);
  184.   BEGIN
  185.     WriteHex (a.SEG,4);
  186.     Write (':');
  187.     WriteHex (a.OFS,4);
  188.   END WriteAddr;
  189.  
  190. PROCEDURE step (name: Str4; proc, prev: ADDRESS): BOOLEAN;
  191.   BEGIN
  192.     WriteString (name);
  193.     WriteString (' at: ');
  194.     WriteAddr (norm(proc));
  195.     WriteString (', prev: ');
  196.     WriteAddr (prev);
  197.     WriteLn;
  198.     RETURN TRUE
  199.   END step;
  200.  
  201. PROCEDURE check;
  202.   BEGIN
  203.     WriteLn;
  204.     Query (ADR (v), step)
  205.   END check;
  206.  
  207. PROCEDURE test;
  208.   (*
  209.    * Verschiedene Fälle:
  210.    *   1. kein Aufruf vorher installierter Routinen
  211.    *   2. Aufruf des Vorgängers als Unterprogramm
  212.    *   3. Aufruf des Vorgängers am Ende.
  213.    * Maβnahmen
  214.    *   für 2.: Carrier.prev einfach per 'Jump to subroutine' aufrufen
  215.    *   für 3.: CPU-Register wiederherstellen, 'Jump' ausführen.
  216.    *)
  217.   BEGIN
  218.     info ('Dies ist die Test-Routine 1')
  219.   END test;
  220.  
  221. PROCEDURE test2;
  222.   BEGIN
  223.     info ('Dies ist die Test-Routine 2')
  224.   END test2;
  225.  
  226. VAR v: PROC;
  227.     at, entry: ADDRESS;
  228.     removable, ok: BOOLEAN;
  229.     carr2, carrier: Carrier;
  230.  
  231. BEGIN
  232.   v:= test2;
  233.   check;
  234.   IF NOT Installed ('Test', ADR (v), at) THEN
  235.     info ('Installiere');
  236.     Create (carrier, 'Test', test, entry);
  237.     Install (entry, at)
  238.   END;
  239.   check;
  240.   info ('Aufruf');
  241.   v;
  242.   IF NOT Installed ('Tes2', ADR (v), at) THEN
  243.     info ('Installiere 2');
  244.     Create (carr2, 'Tes2', test2, entry);
  245.     Install (entry, at)
  246.   END;
  247.   check;
  248.   info ('Aufruf');
  249.   v;
  250.   IF Installed ('Tes2', ADR (v), at) THEN
  251.     info ('2 Wird entfernt');
  252.     Remove (at)
  253.   ELSE
  254.     info ('2 Nicht installiert')
  255.   END;
  256.   check;
  257.   info ('Aufruf');
  258.   v;
  259.   IF Installed ('Test', ADR (v), at) THEN
  260.     info ('1 Wird entfernt');
  261.     Remove (at)
  262.   ELSE
  263.     info ('1 Nicht installiert')
  264.   END;
  265.   check
  266. END XBRA.
  267. ə]);
  268.   END equal;
  269.  
  270. PROCEDURE sub (p: ADDRESSə